#ifndef __CONTACT_MODEL_INTERFACE_V1_1_0__
#define __CONTACT_MODEL_INTERFACE_V1_1_0__

#ifdef WIN32
	#ifdef __cplusplus
		#define EXPORT_MACRO extern "C" __declspec(dllexport)
	#else
		#define EXPORT_MACRO __declspec(dllexport)
	#endif
#else
	#ifdef __cplusplus
		#define EXPORT_MACRO extern "C"
	#else
		#define EXPORT_MACRO
	#endif
#endif

//Return values from CALCULATEFORCE
#define CM_SUCCESS                  0
#define CM_ERR_NO_PREFERENCES_FILE -1

//interface version info (not to be modified)
#define CM_INTERFACE_MAJOR_VERSION 0x01
#define CM_INTERFACE_MINOR_VERSION 0x01
#define CM_INTERFACE_SUB_VERSION   0x00

//size of strings passed into functions (not to be modified)
#define CM_PREF_FILE_BUFF_SIZE  128
#define CM_PROP_NAME_BUFF_SIZE 1024

// Macros for property data types
#define CM_PROP_DATA_TYPE_DOUBLE 0

// macros for property unit types
#define CM_PROP_UNIT_TYPE_OTHER                0
#define CM_PROP_UNIT_TYPE_NONE                 1
#define CM_PROP_UNIT_TYPE_ACCELERATION         2
#define CM_PROP_UNIT_TYPE_ANGLE                3
#define CM_PROP_UNIT_TYPE_ANGULAR_ACELERATION  4
#define CM_PROP_UNIT_TYPE_ANGULAR_VELOCITY     5
#define CM_PROP_UNIT_TYPE_DENSITY              6
#define CM_PROP_UNIT_TYPE_ENERGY               7
#define CM_PROP_UNIT_TYPE_WORK_FUNCTION        8
#define CM_PROP_UNIT_TYPE_FORCE                9
#define CM_PROP_UNIT_TYPE_CHARGE              10
#define CM_PROP_UNIT_TYPE_LENGTH              11
#define CM_PROP_UNIT_TYPE_MASS                12
#define CM_PROP_UNIT_TYPE_MOI                 13
#define CM_PROP_UNIT_TYPE_SHEAR_MOD           14
#define CM_PROP_UNIT_TYPE_TIME                15
#define CM_PROP_UNIT_TYPE_TORQUE              16
#define CM_PROP_UNIT_TYPE_VELOCITY            17
#define CM_PROP_UNIT_TYPE_VOLUME              18
#define CM_PROP_UNIT_TYPE_FREQUENCY           19
#define CM_PROP_UNIT_TYPE_TEMPERATURE         20
#define CM_PROP_UNIT_TYPE_HEAT_FLUX           21


/* This function should not be modified */
EXPORT_MACRO int GETCMINTERFACEVERSION()
{
	return (CM_INTERFACE_MAJOR_VERSION << 16 | CM_INTERFACE_MINOR_VERSION << 8 | CM_INTERFACE_SUB_VERSION);
}

/*
 * The following functions require to be implemented before your plugin
 * can be loaded and used:
 *
 * GETCMPREFERENCEFILE
 *     returns the name of the config file used by this contact model (if any)
 *
 * CALCULATEFORCE
 *     does the actual force calculation for the contact
 *
 * REGISTERNEWPARTICLEPROPERTY
 *     Called by Edem to inform the plugin of a new finalised custom property
 *
 * GETNUMBEROFREQUIREDPROPERTIES
 *     Called by Edem to query the number of custom properties required
 *     by this plugin to run.
 *
 * GETDETAILSFORPROPERTY
 *     Returns the details for the custom properties required for this plugin
 *     to run.
 *
 * If a plugin does not care about custom properties then the implementations of
 * REGISTERNEWPARTICLEPROPERTY, GETNUMBEROFREQUIREDPROPERTIES, and
 * GETDETAILSFORPROPERTY can be stubbed
 */

/**
 * Specifies the name of the config file used by the plugin.
 * @param caPrefFile (Return value) A character array to be populated with the
 *                   config file name.
 *                   This path is relative to the directory the plugin is stored in.
 */
EXPORT_MACRO void GETCMPREFERENCEFILE(char caPrefFile[CM_PREF_FILE_BUFF_SIZE]);

/*
 * This function is called when two elements are in contact with each other.
 *
 * These elements may be surfaces, in which case they are in contact when
 * their contact radii cross, or they are a surface and a geometry element,
 * in which case it is when the contact radius of the surface touches the
 * surface. In this function the two elements are named 1 and 2.
 *
 * The function should return a value to indicate success or failure (see
 * error codes defined above).
 *
 *
 * For additional information please see the help, or one of the
 * examples included in with the product.
 *
 * The following parameters are taken in by the function (and should not be altered):
 *
 * GENERAL INFO
 * ------------
 * sPrefFile           - name & location of the optional preferences file.
 * nTime               - current time
 * nTimestep           - timestep used in simulation
 *
 * ELEMENT INFORMATION
 * -------------------
 * bIsSurf      - 1 if this element is a surface, 0 if not.
 * nId          - the id of the element.
 * sType        - a char * containing the particle template this surface was created from if bIsSurf is 1
 *                OR the name of the geometry section if bIsSurf is 0.
 * nMass        - the mass of the parent particle if bIsSurf is 1, otherwise a large number (usually 1e8) if bIsSurf is 0.
 * nShearMod    - the shear modulus of the element.
 * nPoisson     - Poisson's ratio of the element.
 * nContactCurvature  - the local contact curvature of the element at the contact point.
 * nPhysicalCurvature - the local physical curvature of the element at the contact point.
 * nPosX,Y,Z    - the x, y, z coordinates of the centroid of the element (NOT necessarily the particle).
 * nVelX,Y,Z    - the x, y, z components of velocity the element <i>at the contatc point</i>.
 * nAngVelX,Y,Z - the x, y, z components of angular velocity of the element.
 * charge       - The charge of the element (In C)
 * workFunction - The work function of the element (in Joules)
 * orientation  - A 9 element array containing the orientation matrix for this element
 *                The elements of the array are in the following order:
 *                    XX, XY, XZ, YX, YY, YZ, ZX, ZY, ZZ
 * propertyList - Pointer to a double array containing the property list for the surface (if element if a geometry element this is 0)
 *
 * INTERACTION INFORMATION
 * -----------------------
 *
 * nCoeffRest      - the coefficient of restitution.
 * nStaticFriciton - the coefficient of static friction.
 * nRollingFriction- the coefficient of rolling friction.
 *
 * The following information concerns the contact and may be changed if necessary (for example to represent slip):
 *
 * CONTACT INFORMATION
 * -------------------
 *
 * nContactPointX,Y,Z  - the x, y, z coordinates of the location of the centroid of the contact.
 * nOverlapN           - the magnitude of the normal overlap.
 * nOverlapTX,Y,Z      - the x, y, z components of the tangential overlap.
 *
 * The following information concerns the magnitude of the forces and torques on the elements and should be filled
 * in by the user:
 *
 * FORCES & TORQUES
 * ----------------
 *
 * nForceNX,Y,Z    - The x, y, z components of normal force <i>on element 1</i>.
 *           From Newton II the normal force on element 2 is equal and opposite.
 * nUSForceNX,Y,Z  - The x, y, z components of the unsymmetrical normal forces on element 1. These represent the
 *           portion of nForceNX,Y,Z that causes energy loss / gain (eg damping).
 *           These values are <i>not</i> used in the DEM calculation for a time step but
 *           are used to keep a check on the energy in the system. If you are not using dynamic
 *           time stepping then these values may be set to zero.
 *
 * nForceTX,Y,Z    - The x, y, z components on the tangential force on element 1.
 *           From Newton II the tangential force on element 2 is equal and opposite.
 * nUSForceTX,Y,Z  - The x, y, z components of the unsymmetrical tangential forces on element 1. These represent the
 *           portion of nForceTX,Y,Z that causes energy loss / gain (eg damping).
 *           These values are <i>not</i> used in the DEM calculation for a time step but
 *           are used to keep a check on the energy in the system. If you are not using dynamic
 *           time stepping then these values may be set to zero.
 *
 * nAdditionalTorque1X,Y,Z - The x, y, z coordinates of any additional torque on element 1
 *               <i>not accounted for by the above forces</i> (which are deemed to act at the contact point).
 *               These can be useful, for example, in a consideration of rolling friction.
 * nAdditionalTorque2X,Y,Z - The x, y, z coordinates of any additional torque on element 2
 *               <i>not accounted for by the above forces</i> (which are deemed to act at the contact point).
 *               These can be useful, for example, in a consideration of rolling friction.
 *
 * nUSAdditionalTorque1X,Y,Z - The x, y, z coordinates of any unsymmetrical, additional torque on element 1
 *                 <i>not accounted for by the above forces<i>. These represent the component of the additional
 *                 torque that causes energy loss / gain (eg damping).
 *                 These values are <i>not</i> used in the DEM calculation for a time step but
 *                 are used to keep a check on the energy in the system. If you are not using dynamic
 *                 time stepping then these values may be set to zero
 *
 * chargeMovedToSurface1 - The amount of charge moved from element 2 to element 1 (if negative
 *                         charge moves from element 1 to 2.
 *
 * propertyListChanges - array of double values the same length as the corresponding propertyList
 *                       populated with deltas to the values where needed.
 *                       Unlike other parameters propertyListChanges1 and propertyListChanges2 may already
 *                       contain data that we do not want to loose (changes from prior contacts).  Do not
 *                       set these arrays to 0 and add or subtract your changes from the existing values
 *
 * For additional information please see the help, or one of the examples included in with the product.
 */
EXPORT_MACRO int CALCULATEFORCE(const char *sPrefFile, double *nTime, double *nTimestep,
								int *bIsSurf1, int *nId1, const char *sType1, double *nMass1,
								double *nShearMod1, double *nPoisson1,
                                double *nContactCurvature1, double *nPhysicalCurvature1,double *nPos1X, double *nPos1Y, double *nPos1Z,
                                double *nVel1X, double *nVel1Y, double *nVel1Z,
                                double *nAngVel1X, double *nAngVel1Y, double *nAngVel1Z,
                                double* charge1, double* workFunction1,
                                double* orientation1,
                                int * bIsSurf2, int *nId2, const char *sType2, double *nMass2,
                                double *nShearMod2, double *nPoisson2,
                                double *nContactCurvature2, double *nPhysicalCurvature2,double *nPos2X, double *nPos2Y, double *nPos2Z,
                                double *nVel2X, double *nVel2Y, double *nVel2Z,
                                double *nAngVel2X, double *nAngVel2Y, double *nAngVel2Z,
                                double* charge2, double* workFunction2,
                                double* orientation2,
                                double *nCoeffRest, double *nStaticFriction,  double *nRollingFriction,
                                double *nContactPointX, double *nContactPointY, double *nContactPointZ,
                                double *nOverlapN, double *nOverlapTX, double *nOverlapTY, double *nOverlapTZ,
                                double* propertyList1, double* propertyList2,
                                double *nForceNX, double *nForceNY, double *nForceNZ,
                                double *nUSForceNX, double *nUSForceNY, double *nUSForceNZ,
                                double *nForceTX, double *nForceTY, double *nForceTZ,
                                double *nUSForceTX, double *nUSForceTY, double *nUSForceTZ,
                                double *nAdditionalTorque1X, double *nAdditionalTorque1Y, double *nAdditionalTorque1Z,
                                double *nUSAdditionalTorque1X, double *nUSAdditionalTorque1Y, double *nUSAdditionalTorque1Z,
                                double *nAdditionalTorque2X, double *nAdditionalTorque2Y, double *nAdditionalTorque2Z,
                                double *nUSAdditionalTorque2X, double *nUSAdditionalTorque2Y, double *nUSAdditionalTorque2Z,
                                double* chargeMovedToSurface1,
                                double* propertyListChanges1, double* propertyListChanges2);

/**
 * Registers a new finalised property with the plugin.
 * As each custom particle property becomes finalised (available for use) this
 * method will be called with the details of the property.  A plugin
 * cannot use a property until it has been registered with it via this method
 * For details of how properties are represented see the CALCULATEFORCE method
 *
 * If the plugin does not make use of custom properties this method can be
 * an empty stub that does nothing.
 *
 * @param name             The name of the property (null terminated string)
 * @param numberOfElements The number of elements in the property
 * @param dataType         The data type of the property, currently allways
 *                         CM_PROP_DATA_TYPE_DOUBLE
 * @param offset           The offset in a 1D property array to the first
 *                         element of the properties data.
 */
EXPORT_MACRO void REGISTERNEWPARTICLEPROPERTY(const char* name,
                                              unsigned int* numberOfElements,
                                              unsigned int* dataType,
                                              unsigned int* unitType,
                                              unsigned int* offset);
/**
 * Returns the number of custom properties this plugin wishes to
 * register with the system.
 *
 * If the plugin does not use custom properties this method should return 0.
 *
 * @return The number of custom properties the plugin wishes to

 *         register.
 */
EXPORT_MACRO unsigned int GETNUMBEROFREQUIREDPROPERTIES();

/**
 * Retrieves details for a given property.  This method can be
 * called for propertyIndex values 0...(GETNUMBEROFREQUIREDPROPERTIES() - 1) to
 * retrieve the details for that property from the plugin.  These properties
 * will then be registered with the system if they do not clash with any
 * existing properties.
 *
 * A plugin cannot make use of any properties, even those it registers, until
 * it has been informed of them via the REGISTERNEWPARTICLEPROPERTY method
 * as until then it does not know the offset to the property data.  The plugin
 * cannot assume the properties it regisers will appear in any specific order.
 *
 * If the plugin does not use custom properties this method should allways
 * return false
 *
 * @param propertyIndex    The index of the property to retrieve data for
 * @param name             (Return value) A CM_PROP_NAME_BUFF_SIZE char array
 *                         is supplied to be populated with the name of the
 *                         property
 * @param dataType         (Return value) Should allways be set to
 *                         CM_PROP_DATA_TYPE_DOUBLE
 * @param numberOfElements (Return value) The number of elements (min 1)
 * @param unitType         (Return value) The unit type of the property
 * @return bool to say if data exists for the property
 */
EXPORT_MACRO bool GETDETAILSFORPROPERTY(unsigned int* propertyIndex,
                                        char name[CM_PROP_NAME_BUFF_SIZE],
                                        unsigned int* dataType,
                                        unsigned int* numberOfElements,
                                        unsigned int* unitType);
#endif

